// SitRepEntry.cs
//
// Copyright (c) 2007 Mike Strobel
//
// This source code is subject to the terms of the Microsoft Reciprocal License (Ms-RL).
// For details, see <http://www.opensource.org/licenses/ms-rl.html>.
//
// All other rights reserved.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.Serialization;
using System.Text;
using System.Xml.Linq;

using Supremacy.Expressions.Serialization;

using Supremacy.Entities;
using Supremacy.Orbitals;
using Supremacy.Personnel;
using Supremacy.Resources;
using Supremacy.Scripting;
using Supremacy.Tech;
using Supremacy.Universe;
using Supremacy.Diplomacy;

namespace Supremacy.Game
{
    /// <summary>
    /// Serverity of a situation report entry
    /// </summary>
    public enum SitRepPriority
    {
        /// <summary>
        /// A green situation report entry reflects a normal or informal status message.
        /// </summary>
        Green,
        /// <summary>
        /// A yellow situation report entry reflects a status message, where the player should consider to react.
        /// </summary>
        Yellow,
        /// <summary>
        /// A red siutation report entry reflects a urgend status message. The play must react.
        /// </summary>
        Red,
        /// <summary>
        /// A special event, like a battle, or an event.
        /// </summary>
        Special
    }

    [Flags]
    public enum SitRepCategory
    {
        General = 0x00000001,
        NewColony = 0x00000002,
        ColonyStatus = 0x00000004,
        Construction = 0x00000008,
        Resources = 0x00000010,
        Diplomacy = 0x00000020,
        Military = 0x00000040,
        Research = 0x00000080,
        Intelligence = 0x00000100,
        SpecialEvent = 0x00000200,
        FirstContact = 0x00000400,
        Personnel = 0x00000800,
    }

    /// <summary>
    /// Base class for all SitRep entries.
    /// </summary>
    [Serializable]
    public abstract class SitRepEntry
    {
        private readonly int _ownerId;
        private readonly SitRepPriority _priority;

        /// <summary>
        /// Gets the owner ID.
        /// </summary>
        /// <value>The owner ID.</value>
        protected int OwnerID
        {
            get { return _ownerId; }
        }

        /// <summary>
        /// Gets the owner.
        /// </summary>
        /// <value>The owner.</value>
        public Civilization Owner
        {
            get { return GameContext.Current.Civilizations[_ownerId]; }
        }

        public abstract SitRepCategory Categories { get; }

        /// <summary>
        /// Gets the priority.
        /// </summary>
        /// <value>The priority.</value>
        public SitRepPriority Priority
        {
            get { return _priority; }
        }

        /// <summary>
        /// Gets the summary text.
        /// </summary>
        /// <value>The summary text.</value>
        public abstract string SummaryText { get; }

        /// <summary>
        /// Gets the header text.
        /// </summary>
        /// <value>The header text.</value>
        public virtual string HeaderText
        {
            get { return this.SummaryText; }
        }

        /// <summary>
        /// Gets a value indicating whether this <see cref="SitRepEntry"/> has detailed text.
        /// </summary>
        /// <value>
        /// <c>true</c> if this <see cref="SitRepEntry"/> has detailed text; otherwise, <c>false</c>.
        /// </value>
        public virtual bool HasDetails
        {
            get { return !string.IsNullOrEmpty(DetailText); }
        }

        public bool HasSoundEffect
        {
            get { return (this.SoundEffect != null); }
        }

        public virtual string SoundEffect
        {
            get { return null; }
        }

        public virtual string SummaryImage
        {
            get { return null; }
        }

        /// <summary>
        /// Gets the detail text.
        /// </summary>
        /// <value>The detail text.</value>
        public virtual string DetailText
        {
            get { return null; }
        }

        /// <summary>
        /// Gets the detail image path.
        /// </summary>
        /// <value>The detail image path.</value>
        public virtual string DetailImage
        {
            get { return null; }
        }

        /// <summary>
        /// Gets a value indicating whether this <see cref="SitRepEntry"/> is a priority entry.
        /// </summary>
        /// <value>
        /// <c>true</c> if this <see cref="SitRepEntry"/> is a priority entry; otherwise, <c>false</c>.
        /// </value>
        public virtual bool IsPriority
        {
            get { return false; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SitRepEntry"/> class.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="priority">The priority.</param>
        protected SitRepEntry(Civilization owner, SitRepPriority priority)
        {
            if (owner == null)
                throw new ArgumentNullException("owner");
            _ownerId = owner.CivID;
            _priority = priority;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SitRepEntry"/> class.
        /// </summary>
        /// <param name="ownerId">The owner ID.</param>
        /// <param name="priority">The priority.</param>
        protected SitRepEntry(GameObjectID ownerId, SitRepPriority priority)
        {
            if (!ownerId.IsValid)
                throw new ArgumentException("invalid Civilization ID", "ownerId");
            _ownerId = ownerId;
            _priority = priority;
        }
    }

    [Serializable]
    public class ResearchCompleteSitRepEntry : SitRepEntry
    {
        private readonly int _applicationId;
        private readonly int[] _newDesignIds;

        public ResearchApplication Application
        {
            get { return GameContext.Current.ResearchMatrix.GetApplication(_applicationId); }
        }

        public override SitRepCategory Categories
        {
            get { return SitRepCategory.Research; }
        }

        public override string SummaryText
        {
            get
            {
                return String.Format(
                    "Research has been completed on {0}.",
                    ResourceManager.GetString(Application.Name));
            }
        }

        public override bool HasDetails
        {
            get { return true; }
        }

        public override string DetailText
        {
            get
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendLine(ResourceManager.GetString(Application.Description));
                if ((_newDesignIds != null) && (_newDesignIds.Length > 0))
                {
                    sb.Append("[nl/]The following technologies are now available:[nl/]");
                    for (int i = 0; i < _newDesignIds.Length; i++)
                    {
                        var design = GameContext.Current.TechDatabase[_newDesignIds[i]];
                        if (design == null)
                            continue;
                        sb.Append("[nl/]");
                        sb.Append(ResourceManager.GetString(design.Name));
                    }
                }
                return sb.ToString();
            }
        }

        public override string DetailImage
        {
            get
            {
                var field = Application.Field;
                if (field != null)
                    return field.Image;
                return base.DetailImage;
            }
        }

        public override bool IsPriority
        {
            get { return true; }
        }

        public ResearchCompleteSitRepEntry(
            Civilization owner, 
            ResearchApplication application,
            ICollection<TechObjectDesign> newDesigns) : base(owner, SitRepPriority.Yellow)
        {
            if (application ==null)
                throw new ArgumentNullException("application");
            _applicationId = application.ApplicationID;
            if (newDesigns != null)
            {
                int i = 0;
                _newDesignIds = new int[newDesigns.Count];
                foreach (TechObjectDesign design in newDesigns)
                {
                    _newDesignIds[i++] = design.DesignID;
                }
            }
        }
    }

    [Serializable]
    public class NewColonySitRepEntry : SitRepEntry
    {
        private readonly int _colonyId;

        public Colony Colony
        {
            get { return GameContext.Current.Universe.Objects[_colonyId] as Colony; }
        }

        public override SitRepCategory Categories
        {
            get { return SitRepCategory.NewColony; }
        }

        public override string SummaryText
        {
            get
            {
                return String.Format(
                    "A new colony has been established in the {0} sector.",
                    Colony.Sector.Name);
            }
        }

        public override bool IsPriority
        {
            get { return true; }
        }

        // ReSharper disable SuggestBaseTypeForParameter
        public NewColonySitRepEntry(Civilization owner, Colony colony)
            : base(owner, SitRepPriority.Green)
        {
            if (colony == null)
                throw new ArgumentNullException("colony");
            _colonyId = colony.ObjectID;
        }
        // ReSharper restore SuggestBaseTypeForParameter
    }

    [Serializable]
    public class ItemBuiltSitRepEntry : SitRepEntry
    {
        private readonly int _itemTypeId;
        private readonly MapLocation _location;

        public TechObjectDesign ItemType
        {
            get { return GameContext.Current.TechDatabase[_itemTypeId]; }
        }

        public MapLocation Location
        {
            get { return _location; }
        }

        public override SitRepCategory Categories
        {
            get { return SitRepCategory.Construction; }
        }

        public override string SummaryText
        {
            get
            {
                return String.Format(
                    "{0} constructed in sector {1}.",
                    ResourceManager.GetString(ItemType.Name),
                    GameContext.Current.Universe.Map[Location].Name);
            }
        }

        public ItemBuiltSitRepEntry(Civilization owner, TechObjectDesign itemType, MapLocation location)
            : base(owner, SitRepPriority.Green)
        {
            if (itemType == null)
                throw new ArgumentNullException("itemType");
            _itemTypeId = itemType.DesignID;
            _location = location;
        }
    }

    [Serializable]
    public class StarvationSitRepEntry : SitRepEntry
    {
        private readonly int _systemId;

        public StarSystem System
        {
            get { return GameContext.Current.Universe.Objects[_systemId] as StarSystem; }
        }

        public override SitRepCategory Categories
        {
            get { return SitRepCategory.ColonyStatus; }
        }

        public override string SummaryText
        {
            get
            {
                return String.Format(
                    "There is starvation in the {0} system.",
                    System.Name);
            }
        }

        public override bool IsPriority
        {
            get { return true; }
        }

        public StarvationSitRepEntry(Civilization owner, Colony colony)
            : base(owner, SitRepPriority.Red)
        {
            if (colony == null)
                throw new ArgumentNullException("colony");
            _systemId = colony.System.ObjectID;
        }
    }

    [Serializable]
    public class OrbitalDestroyedSitRepEntry : SitRepEntry
    {
        private readonly string _name;
        private readonly MapLocation _location;

        public string Name
        {
            get { return _name; }
        }

        public MapLocation Location
        {
            get { return _location; }
        }

        public Sector Sector
        {
            get { return GameContext.Current.Universe.Map[Location]; }
        }

        public override SitRepCategory Categories
        {
            get { return SitRepCategory.Military; }
        }

        public override string SummaryText
        {
            get
            {
                return String.Format(
                    ResourceManager.GetString("SITREP_ORBITAL_DESTROYED"),
                    ResourceManager.GetString(Name),
                    Sector);
            }
        }

        public override bool IsPriority
        {
            get { return false; }
        }

        // ReSharper disable SuggestBaseTypeForParameter
        public OrbitalDestroyedSitRepEntry(Orbital orbital)
            : base(orbital.Owner, SitRepPriority.Yellow)
        {
            if (orbital == null)
                throw new ArgumentNullException("orbital");
            _name = orbital.Name;
            _location = orbital.Location;
        }
        // ReSharper restore SuggestBaseTypeForParameter
    }

    [Serializable]
    public class FirstContactSitRepEntry : SitRepEntry
    {
        private readonly Civilization _civilization;
        private readonly MapLocation _location;

        public Civilization Civilization
        {
            get { return _civilization; }
        }

        public MapLocation Location
        {
            get { return _location; }
        }

        public Sector Sector
        {
            get { return GameContext.Current.Universe.Map[Location]; }
        }

        public override bool HasDetails
        {
            get { return true; }
        }

        public override string DetailImage
        {
            get { return Civilization.Image; }
        }

        public override string DetailText
        {
            get { return Civilization.DiplomacyReport ?? Civilization.Race.Description; }
        }

        public override SitRepCategory Categories
        {
            get { return SitRepCategory.Diplomacy | SitRepCategory.FirstContact; }
        }

        public override string SummaryText
        {
            get
            {
                return String.Format(
                    ResourceManager.GetString("SITREP_FIRST_CONTACT"),
                    ResourceManager.GetString(Civilization.ShortName),
                    Sector);
            }
        }

        public override bool IsPriority
        {
            get { return true; }
        }

        public FirstContactSitRepEntry(Civilization owner, Civilization civilization, MapLocation location)
            : base(owner, SitRepPriority.Yellow)
        {
            if (civilization == null)
                throw new ArgumentNullException("civilization");
            _civilization = civilization;
            _location = location;
        }
    }

    [Serializable]
    public class BuildQueueEmptySitRepEntry : SitRepEntry
    {
        private readonly int _colonyId;
        private readonly bool _shipyardQueue;

        public Colony Colony
        {
            get { return GameContext.Current.Universe.Objects[_colonyId] as Colony; }
        }

        public override SitRepCategory Categories
        {
            get { return SitRepCategory.ColonyStatus | SitRepCategory.Construction; }
        }

        public override string SummaryText
        {
            get
            {
                if (_shipyardQueue)
                {
                    return String.Format(
                        ResourceManager.GetString("SITREP_SHIPYARD_BUILD_QUEUE_EMPTY"),
                        Colony.Name);
                }
                return String.Format(
                    ResourceManager.GetString("SITREP_PLANETARY_BUILD_QUEUE_EMPTY"),
                    Colony.Name);
            }
        }

        public override bool IsPriority
        {
            get { return true; }
        }

        // ReSharper disable SuggestBaseTypeForParameter
        public BuildQueueEmptySitRepEntry(Civilization owner, Colony colony, bool shipyardQueue)
            : base(owner, SitRepPriority.Yellow)
        {
            if (colony == null)
                throw new ArgumentNullException("colony");
            _colonyId = colony.ObjectID;
            _shipyardQueue = shipyardQueue;
        }
        // ReSharper restore SuggestBaseTypeForParameter
    }

    [Serializable]
    public class StipulationTerminatedSitRepEntry : SitRepEntry
    {
        private readonly Stipulation _stipulation;
        private readonly TerminationContext _terminationContext;

        public override SitRepCategory Categories
        {
            get { return SitRepCategory.Diplomacy; }
        }

        public override string SummaryText
        {
            get
            {
                switch (_terminationContext.Reason)
                {
                    case TerminationReason.CancelledBySender:
                        return String.Format(
                            "The {0} have terminated a(n) {1} agreement with us.",
                            _terminationContext.TerminatingParty.ShortName,
                            _stipulation.ShortDescription);
                    case TerminationReason.Expired:
                        return String.Format(
                            "A(n) {1} agreement with the {0} has expired.",
                            _terminationContext.TerminatingParty.ShortName,
                            _stipulation.ShortDescription);
                    default:
                        return String.Format(
                            "A(n) {1} agreement with the {0} has ended.",
                            _terminationContext.TerminatingParty.ShortName,
                            _stipulation.ShortDescription);
                }
            }
        }

        public override bool IsPriority
        {
            get { return true; }
        }

        public StipulationTerminatedSitRepEntry(Civilization owner, Stipulation stipulation, TerminationContext terminationContext)
            : base(owner, SitRepPriority.Yellow)
        {
            if (stipulation == null)
                throw new ArgumentNullException("stipulation");
            if (stipulation == null)
                throw new ArgumentNullException("stipulation");
            _stipulation = stipulation;
            _terminationContext = terminationContext;
        }
    }

    [Serializable]
    public class ProposalAcceptedSitRepEntry : SitRepEntry
    {
        private readonly Proposal _proposal;

        public override SitRepCategory Categories
        {
            get { return SitRepCategory.Diplomacy; }
        }

        public override string SummaryText
        {
            get
            {
                if (_proposal.Recipient == Owner)
                {
                    return String.Format(
                        "We have accepted a proposal from the {0}.",
                        _proposal.Sender.ShortName);
                }
                return String.Format(
                    "The {0} have accepted our proposal.",
                    _proposal.Recipient.ShortName);
            }
        }

        public override bool IsPriority
        {
            get { return true; }
        }

        public ProposalAcceptedSitRepEntry(Civilization owner, Proposal proposal)
            : base(owner, SitRepPriority.Green)
        {
            if (proposal == null)
                throw new ArgumentNullException("proposal");
            _proposal = proposal;
        }
    }

    [Serializable]
    public class ProposalRejectedSitRepEntry : SitRepEntry
    {
        private readonly Proposal _proposal;

        public override SitRepCategory Categories
        {
            get { return SitRepCategory.Diplomacy; }
        }

        public override string SummaryText
        {
            get
            {
                if (_proposal.Recipient == Owner)
                {
                    return String.Format(
                        "We have rejected a proposal from the {0}.",
                        _proposal.Sender.ShortName);
                }
                return String.Format(
                    "The {0} have rejected our proposal.",
                    _proposal.Recipient.ShortName);
            }
        }

        public override bool IsPriority
        {
            get { return true; }
        }

        public ProposalRejectedSitRepEntry(Civilization owner, Proposal proposal)
            : base(owner, SitRepPriority.Yellow)
        {
            if (proposal == null)
                throw new ArgumentNullException("proposal");
            _proposal = proposal;
        }
    }

    [Serializable]
    public class WarDeclaredSitRepEntry : SitRepEntry
    {
        private readonly Civilization _victim;
        private readonly Civilization _aggressor;
        private readonly CivString _detailText;

        public override SitRepCategory Categories
        {
            get { return SitRepCategory.Diplomacy | SitRepCategory.Military; }
        }

        public override string SummaryText
        {
            get
            {
                return String.Format(
                    "The {0} has declared war against the {1}.",
                    this.Aggressor.LongName,
                    this.Victim.LongName);
            }
        }

        public override bool HasDetails
        {
            get { return ((this.Aggressor == this.Owner) || (this.Victim == this.Owner)); }
        }

        public override string DetailImage
        {
            get
            {
                return (this.Owner == this.Aggressor)
                    ? this.Victim.InsigniaPath
                    : this.Aggressor.InsigniaPath;
            }
        }

        public override string DetailText
        {
            get { return String.Format(_detailText.Value, this.Victim.LongName); }
        }

        public override bool IsPriority
        {
            get { return true; }
        }

        public Civilization Victim
        {
            get { return _victim; }
        }

        public Civilization Aggressor
        {
            get { return this._aggressor; }
        }

        public WarDeclaredSitRepEntry(Civilization owner, Civilization victim) : this(owner, owner, victim) {}

        public WarDeclaredSitRepEntry(Civilization owner, Civilization aggressor, Civilization victim)
            : base(owner, SitRepPriority.Red)
        {
            if (aggressor == null)
                throw new ArgumentNullException("aggressor");
            if (victim == null)
                throw new ArgumentNullException("victim");
            _victim = victim;
            _aggressor = aggressor;
            if ((aggressor == owner) || (victim == owner))
            {
                _detailText = new CivString(
                    owner, CivString.DiplomacyCategory,
                    (owner == aggressor) ? "DECLARED_WAR_US_DETAILS" : "DECLARED_WAR_THEM_DETAILS");
            }
        }
    }

    [Serializable]
    public class DiplomaticMessageSitRepEntry : SitRepEntry
    {
        private readonly DiplomaticMessage _message;
        private CivString _headerText;
        private CivString _detailText;
        private string _imagePath;

        public override SitRepCategory Categories
        {
            get { return SitRepCategory.Diplomacy; }
        }

        public override string SummaryText
        {
            get { return String.Format(_headerText.Value, RelevantParty.ShortName, AlternateParty.ShortName); }
        }

        public override bool HasDetails
        {
            get { return ((_detailText != null) && _detailText.HasValue); }
        }

        public override string DetailImage
        {
            get { return _imagePath; }
        }

        public override string DetailText
        {
            get { return String.Format(_detailText.Value, RelevantParty.LongName, AlternateParty.LongName); }
        }

        public override bool IsPriority
        {
            get { return true; }
        }

        protected Civilization RelevantParty
        {
            get
            {
                if (_message.IsReply)
                {
                    if (this.Owner == _message.Sender)
                        return _message.Recipient;
                    return _message.Sender;
                }
                if (this.Owner == _message.Recipient)
                    return _message.Sender;
                return _message.Recipient;
            }
        }

        protected Civilization AlternateParty
        {
            get { return (this.RelevantParty == _message.Sender) ? _message.Recipient : _message.Sender; }
        }

        public DiplomaticMessageSitRepEntry(Civilization owner, DiplomaticMessage message) : base(owner, SitRepPriority.Red)
        {
            if (message == null)
                throw new ArgumentNullException("message");
            _message = message;
            Initialize();
        }

        private void Initialize()
        {
            string headerKey = null;
            string detailsKey = null;
             if (_message.IsReply)
            {
                if (_message.MessageType == DiplomaticMessageType.ProposalAcceptance)
                {
                    var stipulations = _message.Proposal.OfferStipulations.Union(_message.Proposal.DemandStipulations);
                    foreach (Stipulation stipulation in stipulations)
                    {
                        if (stipulation is TreatyStipulation)
                        {
                            if (stipulation is AllianceStipulation)
                            {
                                headerKey = (Owner != RelevantParty)
                                    ? "MESSAGE_SITREP_HEADER_ALLIANCE_ACCEPTED_US"
                                    : "MESSAGE_SITREP_HEADER_ALLIANCE_ACCEPTED_THEM";
                                detailsKey = (Owner != RelevantParty)
                                    ? "MESSAGE_SITREP_DETAILS_ALLIANCE_ACCEPTED_US"
                                    : "MESSAGE_SITREP_DETAILS_ALLIANCE_ACCEPTED_THEM";
                                _imagePath = RelevantParty.InsigniaPath;
                                break;
                            }
                            if (stipulation is MembershipStipulation)
                            {
                                headerKey = (Owner != RelevantParty)
                                                ? "MESSAGE_SITREP_HEADER_MEMBERSHIP_ACCEPTED_US"
                                                : "MESSAGE_SITREP_HEADER_MEMBERSHIP_ACCEPTED_THEM";
                                detailsKey = (Owner != RelevantParty)
                                                 ? "MESSAGE_SITREP_DETAILS_MEMBERSHIP_ACCEPTED_US"
                                                 : "MESSAGE_SITREP_DETAILS_MEMBERSHIP_ACCEPTED_THEM";
                                _imagePath = RelevantParty.InsigniaPath;
                                break;
                            }
                            headerKey = (Owner != RelevantParty)
                                            ? "MESSAGE_SITREP_HEADER_TREATY_ACCEPTED_US"
                                            : "MESSAGE_SITREP_HEADER_TREATY_ACCEPTED_THEM";
                        }
                        else
                        {
                            headerKey = (Owner != RelevantParty)
                                ? "MESSAGE_SITREP_HEADER_PROPOSAL_ACCEPTED_US"
                                : "MESSAGE_SITREP_HEADER_PROPOSAL_ACCEPTED_THEM";
                        }
                    }
                }
                else if (_message.MessageType == DiplomaticMessageType.ProposalRejection)
                {
                    var stipulations = _message.Proposal.OfferStipulations.Union(_message.Proposal.DemandStipulations);
                    foreach (Stipulation stipulation in stipulations)
                    {
                        if (stipulation is TreatyStipulation)
                        {
                            if (stipulation is AllianceStipulation)
                            {
                                headerKey = (Owner != RelevantParty)
                                    ? "MESSAGE_SITREP_HEADER_ALLIANCE_REJECTED_US"
                                    : "MESSAGE_SITREP_HEADER_ALLIANCE_REJECTED_THEM";
                                break;
                            }
                            if (stipulation is MembershipStipulation)
                            {
                                headerKey = (Owner != RelevantParty)
                                                ? "MESSAGE_SITREP_HEADER_MEMBERSHIP_REJECTED_US"
                                                : "MESSAGE_SITREP_HEADER_MEMBERSHIP_REJECTED_THEM";
                                break;
                            }
                            headerKey = (Owner != RelevantParty)
                                            ? "MESSAGE_SITREP_HEADER_TREATY_REJECTED_US"
                                            : "MESSAGE_SITREP_HEADER_TREATY_REJECTED_THEM";
                        }
                        else
                        {
                            headerKey = (Owner != RelevantParty)
                                ? "MESSAGE_SITREP_HEADER_PROPOSAL_REJECTED_US"
                                : "MESSAGE_SITREP_HEADER_PROPOSAL_REJECTED_THEM";
                        }
                    }
                }

            }
            else if (_message.IsStatement)
            {
                headerKey = (Owner != RelevantParty)
                    ? "MESSAGE_SITREP_HEADER_STATEMENT_US"
                    : "MESSAGE_SITREP_HEADER_STATEMENT_THEM";
            }
            else if (_message.IsWarDeclaration)
            {
                headerKey = (Owner != RelevantParty)
                    ? "MESSAGE_SITREP_HEADER_WAR_DECLARATION_US"
                    : "MESSAGE_SITREP_HEADER_WAR_DECLARATION_THEM";
                detailsKey = (Owner == _message.Sender)
                    ? "MESSAGE_SITREP_DETAILS_WAR_DECLARATION_US"
                    : "MESSAGE_SITREP_DETAILS_WAR_DECLARATION_THEM";
                _imagePath = RelevantParty.InsigniaPath;
            }
            else if (_message.IsGift)
            {
                headerKey = (Owner != RelevantParty)
                    ? "MESSAGE_SITREP_HEADER_GIFT_US"
                    : "MESSAGE_SITREP_HEADER_GIFT_THEM";
            }
            else if (_message.IsDemand)
            {
                headerKey = (Owner != RelevantParty)
                    ? "MESSAGE_SITREP_HEADER_DEMAND_US"
                    : "MESSAGE_SITREP_HEADER_DEMAND_THEM";
            }
            else if (_message.IsCounterProposal)
            {
                headerKey = (Owner != RelevantParty)
                    ? "MESSAGE_SITREP_HEADER_COUNTER_PROPOSAL_US"
                    : "MESSAGE_SITREP_HEADER_COUNTER_PROPOSAL_THEM";
            }
            else if (_message.IsProposal)
            {
                headerKey = (Owner != RelevantParty)
                    ? "MESSAGE_SITREP_HEADER_PROPOSAL_US"
                    : "MESSAGE_SITREP_HEADER_PROPOSAL_THEM";
            }
             else if (_message.MessageType == DiplomaticMessageType.AgreementTermination)
             {
                 headerKey = (Owner != RelevantParty)
                     ? "MESSAGE_SITREP_HEADER_AGREEMENT_TERMINATION_US"
                     : "MESSAGE_SITREP_HEADER_AGREEMENT_TERMINATION_THEM";
             }
            
            if (headerKey == null)
            {
                headerKey = (Owner != RelevantParty)
                    ? "We have sent a message to the {0}."
                    : "The {0} have sent us a message.";
            }

            _headerText = new CivString(Owner, CivString.DiplomacyCategory, headerKey, _message.Demeanor);

            if (detailsKey != null)
            {
                _detailText = new CivString(Owner, CivString.DiplomacyCategory, detailsKey, _message.Demeanor);
            }
        }
    }

    [Serializable]
    public class ScriptedEventSitRepEntry : SitRepEntry, ISerializable
    {
        private readonly Expression<Func<object>>[] _parameterResolvers;
        private readonly CivString _headerText;
        private readonly CivString _summaryText;
        private readonly CivString _detailText;
        private readonly string _detailImage;
        private readonly string _soundEffect;

        protected ScriptedEventSitRepEntry(SerializationInfo info, StreamingContext context)
            : base(info.GetInt32("OwnerID"), SitRepPriority.Special)
        {
            var expressionSerializer = new ExpressionSerializer();

            try
            {
                _parameterResolvers = ((string[])info.GetValue("_parameterResolvers", typeof(string[]))).Select(
                    o => (Expression<Func<object>>)expressionSerializer.Deserialize(XElement.Parse(o))).ToArray();
            }
            catch
            {
                if (System.Diagnostics.Debugger.IsAttached)
                    System.Diagnostics.Debugger.Break();

                _parameterResolvers =
                    ((string[])info.GetValue("_parameterResolvers", typeof(string[]))).Select(o => (Expression<Func<object>>)(() => "<error>")).ToArray();
            }

            _headerText = (CivString)info.GetValue("_headerText", typeof(CivString));
            _detailText = (CivString)info.GetValue("_detailText", typeof(CivString));
            _summaryText = (CivString)info.GetValue("_summaryText", typeof(CivString));
            _detailImage = info.GetString("_detailImage");
            _soundEffect = info.GetString("_soundEffect");
        }

        public ScriptedEventSitRepEntry(ScriptedEventSitRepEntryData data)
            : base(data.Owner, SitRepPriority.Special)
        {
            _parameterResolvers = data.DetailTextParameterResolvers;
            _headerText = new CivString(data.Owner, CivString.ScriptedEventsCategory, data.HeaderText);
            _detailText = new CivString(data.Owner, CivString.ScriptedEventsCategory, data.DetailText);
            _summaryText = new CivString(data.Owner, CivString.ScriptedEventsCategory, data.SummaryText);
            _detailImage = data.DetailImage;
            _soundEffect = data.SoundEffect;
        }

        public override string SoundEffect
        {
            get { return _soundEffect; }
        }

        public override string HeaderText
        {
            get { return string.Format(_headerText.Value, _parameterResolvers.Select(f => f.Compile()()).ToArray()); }
        }

        public override SitRepCategory Categories
        {
            get { return SitRepCategory.SpecialEvent; }
        }

        public override string SummaryText
        {
            get { return string.Format(_summaryText.Value, _parameterResolvers.Select(f => f.Compile()()).ToArray()); }
        }

        public override string DetailText
        {
            get { return string.Format(_detailText.Value, _parameterResolvers.Select(f => f.Compile()()).ToArray()); }
        }

        public override string DetailImage
        {
            get { return _detailImage; }
        }

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            var expressionSerializer = new ExpressionSerializer();

            info.AddValue(
                "_parameterResolvers",
                _parameterResolvers.Select(o => expressionSerializer.Serialize(o.CanReduce ? o.Reduce() : o).ToString(SaveOptions.DisableFormatting)).ToArray());

            info.AddValue("OwnerID", base.OwnerID);
            info.AddValue("_headerText", _headerText);
            info.AddValue("_summaryText", _summaryText);
            info.AddValue("_detailText", _detailText);
            info.AddValue("_detailImage", _detailImage);
            info.AddValue("_soundEffect", _soundEffect);
        }
    }

    [Serializable]
    public sealed class NewAgentSitRepEntry : SitRepEntry
    {
        private readonly GameObjectID _agentId;
        private readonly CivString _headerText;
        private readonly CivString _detailText;

        public NewAgentSitRepEntry(Agent agent)
            : base(agent.OwnerID, SitRepPriority.Special)
        {
            _agentId = agent.ObjectID;

            _headerText = new CivString(
                agent.Owner,
                CivString.PersonnelCategory,
                "MESSAGE_SITREP_HEADER_AGENT_RECRUITED");

            _detailText = new CivString(
                agent.Owner,
                CivString.PersonnelCategory,
                "MESSAGE_SITREP_DETAILS_AGENT_RECRUITED");
        }

        public Agent Agent
        {
            get { return GameContext.Current.CivilizationManagers[this.OwnerID].AgentPool.CurrentAgents[_agentId]; }
        }

        #region Overrides of SitRepEntry
        public override SitRepCategory Categories
        {
            get { return SitRepCategory.Personnel;}
        }

        public override string SummaryText
        {
            get { return string.Format(_headerText.Value, this.Agent.Profile.DisplayName); }
        }

        public override string DetailText
        {
            get
            {
                var profile = this.Agent.Profile;

                return string.Format(
                    _detailText.Value,
                    profile.DisplayName,
                    this.Owner.ShortName,
                    string.Join(", ", profile.NaturalSkills));
            }
        }

        public override string DetailImage
        {
            get
            {
                var agent = this.Agent;
                if (agent == null)
                    return null;

                return agent.Profile.Image;
            }
        }

        public override bool IsPriority
        {
            get { return true; }
        }
        #endregion
    }
}
